package com.eastfair.venuebooking.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.eastfair.annotation.annotation.base.BaseControllerInfo;
import com.eastfair.annotation.annotation.log.SysLog;
import com.eastfair.annotation.annotation.security.PreAuth;
import com.eastfair.boot.controller.SuperController;
import com.eastfair.boot.request.PageParams;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;
import com.eastfair.core.base.entity.SuperEntity;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.core.exception.BizException;
import com.eastfair.venuebooking.demand.ExhibitionGroup;
import com.eastfair.venuebooking.dto.*;
import com.eastfair.venuebooking.entity.Exhibition;
import com.eastfair.venuebooking.entity.ProjectExhibition;
import com.eastfair.venuebooking.enumeration.ExhibitionStateEnum;
import com.eastfair.venuebooking.enumeration.VenueBookAuditVenueBookSourceEnum;
import com.eastfair.venuebooking.exceptioncode.VenueBookingExceptionCode;
import com.eastfair.venuebooking.service.*;
import com.eastfair.venuebooking.vo.ExhibitionVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;


/**
 * <p>
 * 前端控制器
 * 展会
 * </p>
 *
 * @author linan
 * @date 2022-06-08
 */
@Slf4j
@Validated
@RestController
@RequestMapping("/exhibition")
@Api(value = "Exhibition", tags = "展会")
@PreAuth(replace = "venuebooking:exhibition:")
public class ExhibitionController extends SuperController<ExhibitionService, Long, Exhibition, ExhibitionPageQuery, ExhibitionSaveDTO, ExhibitionUpdateDTO> {

    @Value("${com.eastfair.projectId}")
    private Long projectId;

    @Resource
    private QuotationService quotationService;
    @Resource
    private ProjectExhibitionService projectExhibitionService;
    @Resource
    private ProjectService projectService;
    @Resource
    private ExhibitionExportService exhibitionExportService;

    @Resource
    private VenueBookAuditService venueBookAuditService;

    @Override
    public void handlerResult(IPage<Exhibition> page) {
        // 想让返回值实现自动回显，请将此行代码打开
        // echoService.action(page);
    }
    /**
     * Excl导入后的操作
     * @param list list
     * @return R<Boolean>
     */
    @Override
    public R<Boolean> handlerImport(List<Map<String, String>> list){
        List<Exhibition> exhibitionList = list.stream().map((map) -> {
            Exhibition exhibition = Exhibition.builder().build();
            //TODO 请在这里完成转换
            return exhibition;
        }).collect(Collectors.toList());

        return R.success(baseService.saveBatch(exhibitionList));
    }



    /**
     * 处理参数
     *
     * @param params 分页参数
     */
    @Override
    public void handlerQueryParams(PageParams<ExhibitionPageQuery> params) {
        ExhibitionPageQuery pageQuery = params.getModel();
        //分页处理
        if(ContextUtil.getProjectId()!=null){
            pageQuery.setProjectId(ContextUtil.getProjectId());
        }
    }


    /**
     * 近期展览/会议/其他
     *
     * @param params params
     * @return R<Page<ExhibitionVO>>
     */
    @ApiOperation(value = "近期展览/会议/其他", notes = "近期展览/会议/其他")
    @PostMapping("/queryRecentExhibitionList")
    @BaseControllerInfo(voGroup = {ExhibitionGroup.queryExhibitionList.class})
    public R<IPage<ExhibitionVO>> queryRecentExhibitionList(@RequestBody PageParams<ExhibitionQuery> params) {
        log.info("queryRecentExhibitionList - 近期展览/会议/其他 params={}", params);
        return R.success(baseService.queryRecentExhibitionList(params));
    }

    /**
     * 展会列表
     *
     * @param params params
     * @return R<Page<ExhibitionVO>>
     */
    @ApiOperation(value = "展会列表", notes = "展会列表")
    @PostMapping("/queryExhibitionList")
    @BaseControllerInfo(voGroup = {ExhibitionGroup.queryExhibitionList.class})
    public R<IPage<ExhibitionVO>> queryExhibitionList(@RequestBody PageParams<ExhibitionQuery> params) {
        log.info("queryExhibitionList - 展会列表 params={}", params);
        return R.success(baseService.queryExhibitionList(params));
    }

    /**
     * 展会列表
     *
     * @param params params
     * @return R<Page<ExhibitionVO>>
     */
    @ApiOperation(value = "展会列表（跳过鉴权）", notes = "展会列表（跳过鉴权）")
    @PostMapping("/queryExhibitionListForExternal")
    @BaseControllerInfo(voGroup = {ExhibitionGroup.queryExhibitionList.class})
    public R<IPage<ExhibitionVO>> queryExhibitionListForExternal(@RequestBody PageParams<ExhibitionQuery> params) {
        log.info("queryExhibitionList - 展会列表（跳过鉴权） params={}", params);
        ContextUtil.setProjectId(projectId);
        ExhibitionQuery model = params.getModel();
        model.setExhibitionEndTime(LocalDateTime.now());
        return R.success(baseService.queryExhibitionList(params));
    }

    /**
     * 添加展会
     *
     * @param exhibitionSaveDTO 添加展会实体
     * @return R
     */
    @ApiOperation(value = "添加展会", notes = "添加展会")
    @SysLog("添加展会")
    @PostMapping("/addExhibition")
    public R addExhibition(@RequestBody @Validated(ExhibitionDTO.Check.class) ExhibitionDTO exhibitionSaveDTO) {
        log.info("addExhibition - 添加展会 exhibitionSaveDTO={}", exhibitionSaveDTO);
        return baseService.addExhibition(exhibitionSaveDTO);
    }

    /**
     * 复制展会
     *
     * @param exhibitionSaveDTO 复制展会
     * @return R
     */
    @ApiOperation(value = "复制展会", notes = "复制展会")
    @SysLog("复制展会")
    @PostMapping("/copyExhibition")
    public R copyExhibition(@RequestBody @Validated(ExhibitionDTO.CopyCheck.class) ExhibitionDTO exhibitionSaveDTO) {
        log.info("copyExhibition - 复制展会 exhibitionSaveDTO={}", exhibitionSaveDTO);
        return baseService.copyExhibition(exhibitionSaveDTO);
    }

    /**
     * 更新展会信息
     *
     * @param exhibitionUpdateDTO 更新展会信息
     * @return R
     */
    @ApiOperation(value = "更新展会信息", notes = "更新展会信息")
    @SysLog("修改展会")
    @PostMapping("/updateExhibition")
    public R updateExhibition(@RequestBody @Validated({ExhibitionDTO.Check.class, SuperEntity.Update.class}) ExhibitionDTO exhibitionUpdateDTO) {
        log.info("updateExhibition - 更新展会信息 exhibitionUpdateDTO={}", exhibitionUpdateDTO);
        return baseService.updateExhibition(exhibitionUpdateDTO);
    }

    /**
     * 确认展会
     *
     * @param exhibitionId 确认展会
     * @return R
     */
    @ApiOperation(value = "确认展会", notes = "确认展会")
    @SysLog("确认展会")
    @GetMapping("/updateConfirmExhibition")
    public R<Boolean> updateConfirmExhibition(@RequestParam(value = "exhibitionId") @Validated @NotNull(message = "展会ID必填")  Long exhibitionId) {
        log.info("updateConfirmExhibition - 确认展会 exhibitionId={}", exhibitionId);
        return R.success(baseService.updateConfirmExhibition(exhibitionId));
    }

    /**
     * 同步展会
     *
     * @param exhibitionId 同步展会
     * @return
     */
    @ApiOperation(value = "同步展会", notes = "同步展会")
    @GetMapping("/updateSynchronousSegment")
    public R updateSynchronousSegment(@RequestParam(value = "exhibitionId") @Validated @NotNull(message = "展会ID必填")  Long exhibitionId) {
        log.info("updateSynchronousSegment - 同步展会 exhibitionId={}", exhibitionId);
        if(Objects.nonNull(exhibitionId)){
            Exhibition exhibition = baseService.getById(exhibitionId);
            if(Objects.nonNull(exhibition)){
                baseService.updateAutoSegment(exhibition);
                // 同步展会到综合服务
                baseService.syncExhibition(exhibition);
                // 同步展会到外部小程序
                baseService.syncExhibitionToOutside(exhibition);
            }
        }
        return R.success();
    }

    /**
     * 同步展会到外部小程序
     *
     * @param exhibitionId 同步展会到外部小程序
     * @return
     */
    @ApiOperation(value = "同步展会到外部小程序", notes = "同步展会到外部小程序")
    @GetMapping("/syncExhibitionToOutside")
    public R syncExhibitionToOutside(@RequestParam(value = "exhibitionId") @Validated @NotNull(message = "展会ID必填")  Long exhibitionId) {
        log.info("updateSynchronousSegment - 同步展会 exhibitionId={}", exhibitionId);
        if(Objects.nonNull(exhibitionId)){
            Exhibition exhibition = baseService.getById(exhibitionId);
            if(Objects.nonNull(exhibition)){
                // 同步展会到外部小程序
                baseService.syncExhibitionToOutside(exhibition);
            }
        }
        return R.success();
    }

    /**
     * 删除展会
     *
     * @param exhibitionId 删除展会
     * @return
     */
    @ApiOperation(value = "删除展会", notes = "删除展会")
    @SysLog("删除展会")
    @GetMapping("/delExhibition")
    public R delExhibition(@RequestParam(value = "exhibitionId") @Validated @NotNull(message = "展会ID必填")  Long exhibitionId) {
        log.info("delExhibition - 删除展会 exhibitionId={}",exhibitionId);
        Exhibition updateEntity = Exhibition.builder().id(exhibitionId).isDeleted(BusinessConstant.YES).build();
        // 删除展会
        boolean b = baseService.updateById(updateEntity);
        // 更新项目数量
        QueryWrapper<ProjectExhibition> projectExhibitionQueryWrapper = new QueryWrapper<>();
        projectExhibitionQueryWrapper.lambda().eq(ProjectExhibition::getExhibitionId,exhibitionId).eq(ProjectExhibition::getIsDeleted,BusinessConstant.NO);
        List<Long> exhibitionProjectIds = projectExhibitionService.list(projectExhibitionQueryWrapper).stream().map(ProjectExhibition::getExhibitionProjectId).collect(Collectors.toList());
        projectExhibitionService.update(new UpdateWrapper<ProjectExhibition>().lambda()
                .eq(ProjectExhibition::getExhibitionId,exhibitionId)
                .eq(ProjectExhibition::getIsDeleted,BusinessConstant.NO)
                .set(ProjectExhibition::getIsDeleted,BusinessConstant.YES));
        for (Long exhibitionProjectId : exhibitionProjectIds) {
            projectService.updateExhibitionSum(exhibitionProjectId);
        }
        return R.success(b);
    }

    /**
     * 关联报价书
     *You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
     * @param exhibitionId 展会id
     * @return
     */
    @ApiOperation(value = "关联报价书", notes = "关联报价书")
    @SysLog("关联报价书")
    @GetMapping("/updateRelatedQuotation")
    public R updateRelatedQuotation(@RequestParam(value="exhibitionId") @Validated @NotNull(message = "展会ID必填")  Long exhibitionId,
                              @RequestParam(value="quotationIds") @Validated @NotEmpty(message = "报价书ID必填") List<Long> quotationIds) {
        log.info("updateRelatedQuotation - 关联报价书  展会id: {},报价书id: {} 关联报价书",exhibitionId,quotationIds);
        for (Long quotationId : quotationIds) {
            QuotationDTO quotation = new QuotationDTO();
            quotation.setId(quotationId);
            quotation.setExhibitionId(exhibitionId);
            quotationService.saveExhibitionQuotation(quotation);
        }
        baseService.updateById(Exhibition.builder().id(exhibitionId).quotationId(quotationIds.get(0)).build());
        return R.success(baseService.updateExhibitionState(exhibitionId,ExhibitionStateEnum.STATE_THREE));
    }

    /**
     * 修改展会状态
     *
     * @param exhibitionId 展会id
     * @return
     */
    @ApiOperation(value = "修改展会状态", notes = "修改展会状态")
    @SysLog("修改展会状态")
    @GetMapping("/updateExhibitionState")
    public R updateExhibitionState(@RequestParam(value="exhibitionId") @Validated @NotNull(message = "展会ID必填")  Long exhibitionId,
                              @RequestParam(value="state") @Validated @NotNull(message = "状态值必填")  ExhibitionStateEnum state) {
        log.info("updateExhibitionState - 修改展会状态   展会id: {},展会状态id: {} ",exhibitionId,state);
        return R.success(baseService.updateExhibitionState(exhibitionId,state));
    }

    /**
     * 展会日历
     *
     * @param
     * @return
     */
    @ApiOperation(value = "展会日历", notes = "展会日历")
    @GetMapping("/getExhibitionCalendar")
    public R<Map<String, Object>> getExhibitionCalendar(@RequestParam(value="keywords",required = false) String keywords) {
        log.info("exhibitionCalendar - 展会日历   keywords: {}",keywords);
        return R.success(baseService.getExhibitionCalendar(keywords));
    }

    /**
     * 项目进度、场地预订情况、合同金额、任务执行
     *
     * @param exhibitionId 展会ID
     * @return R
     */
    @ApiOperation(value = "项目进度、场地预订情况、合同金额、任务执行", notes = "项目进度、场地预订情况、合同金额、任务执行")
    @GetMapping("/getStatisticalItems")
    public R getStatisticalItems(@RequestParam("exhibitionId") @Validated @NotNull(message = "展会ID不能为空") Long exhibitionId) {
        log.info("getStatisticalItems - 项目进度、场地预订情况、合同金额、任务执行   展会id: {}",exhibitionId);
        return R.success(baseService.getStatisticalItems(exhibitionId));
    }

    /**
     * 统筹书展示
     *
     * @param exhibitionId 展会ID
     * @param date 日期
     * @return R<Map<String, Object>>
     */
    @ApiOperation(value = "统筹书展示", notes = "统筹书展示")
    @GetMapping("/getCoordinationBookView")
    public R<Map<String, Object>> getCoordinationBookView(@RequestParam("exhibitionId") @Validated @NotNull(message = "展会ID不能为空")Long exhibitionId,LocalDate date) {
        log.info("getCoordinationBookView - 统筹书展示   exhibitionId: {},date: {}",exhibitionId,date);
        Exhibition exhibition = baseService.getById(exhibitionId);
        if(Objects.nonNull(exhibition)){
            Map<String, Object> result = new HashMap<>(8);
            return R.success(baseService.getCoordinationBookView(exhibitionId,date,exhibition,result));
        }else {
            throw BizException.wrap(VenueBookingExceptionCode.EX_NOT_FIND_EXHIBITION);
        }
    }

    /**
     * 导出统筹书
     * @param exhibitionId exhibitionId
     * @param date date
     * @param response response
     */
    @ApiOperation(value = "导出统筹书", notes = "导出统筹书")
    @GetMapping("/exportCoordinationBook")
    public void exportCoordinationBook(@RequestParam("exhibitionId") @Validated @NotNull(message = "展会ID不能为空")Long exhibitionId,LocalDate date, HttpServletResponse response) {
        log.info("exportCoordinationBook - 导出统筹书   exhibitionId: {},date: {}",exhibitionId,date);
        exhibitionExportService.exportCoordinationBook(exhibitionId,date,response);
    }

    /**
     * 同步综合展会管理信息
     * @param exhibitionDTO exhibitionDTO
     * @return R<Boolean>
     */
    @ApiOperation(value = "同步综合展会管理信息", notes = "同步综合展会管理信息")
    @PostMapping("/syncExhibitionManage")
    public R<Boolean> syncExhibitionManage(@RequestBody ExhibitionDTO exhibitionDTO){
        return R.success(baseService.syncExhibitionManage(exhibitionDTO));
    }

    /**
     * 检查展会是否需要更新合同.
     *
     * @param exhibitionUpdateDTO the exhibition update dto
     * @return the r
     */
    @ApiOperation(value = "检查展会是否需要更新合同", notes = "检查展会是否需要更新合同")
    @PostMapping("/check/contractManage/update")
    public R<Boolean> checkUpdateContactInfo(@RequestBody
                                             @Validated({ExhibitionDTO.Check.class, SuperEntity.Update.class})
                                             ExhibitionDTO exhibitionUpdateDTO) {
        log.info("checkUpdateContactInfo - 检查展会是否需要更新合同, updateDTO={}", exhibitionUpdateDTO);
        return R.successDef(baseService.checkIsUpdateContract(exhibitionUpdateDTO));
    }

    /**
     * 查询展会项目名称
     * @param exhibitionId exhibitionId
     * @return R
     */
    @ApiOperation(value = "查询展会项目名称", notes = "查询展会项目名称")
    @GetMapping("/queryProjectName")
    public R<String> queryProjectName(@RequestParam("exhibitionId") Long exhibitionId) {
        log.info("queryProjectName - 查询展会项目名称   exhibitionId: {}",exhibitionId);
        return R.success(projectExhibitionService.queryProjectName(exhibitionId));
    }

    /**
     * 查询展会未同步的所有展会
     *
     * @return R
     */
    @ApiOperation(value = "查询展会未同步的所有展会", notes = "查询展会未同步的所有展会")
    @PostMapping("/queryNeedSyncExhibition")
    public R<List<ExhibitionVO>> queryNeedSyncExhibition() {
        log.info("queryNeedSyncExhibition - 查询展会未同步的所有展会");
        return R.success(baseService.queryNeedSyncExhibition());
    }


    /**
     * 外部系统提交场馆预定审核.
     *
     * @param venueBookAuditDTO the venue book audit dto
     * @return the r
     */
    @ApiOperation(value = "外部系统提交场馆预定审核", notes = "外部系统提交场馆预定审核")
    @PostMapping("/syncWebsiteExhibition")
    public R<Boolean> saveVenueBookAudit(@RequestBody @Validated({VenueBookAuditDTO.Save.class}) VenueBookAuditDTO venueBookAuditDTO) {
        log.info("saveVenueBook - 外部系统提交场馆预定审核, venueBookAuditDTO={}", venueBookAuditDTO);
        // 此接口本来应该放在VenueBookAuditController里，放在这儿是因为对外提供的接口文档已经给出去了，不想再改接口路径了，所以就这么地吧
        ContextUtil.setProjectId(projectId);
        return R.success(venueBookAuditService.saveForVenueWebSite(venueBookAuditDTO));
    }


    /**
     * 校验是否存在同期展会.
     *
     * @param exhibitionDTO exhibitionDTO
     * @return the r
     */
    @ApiOperation(value = "校验是否存在同期展会", notes = "校验是否存在同期展会")
    @PostMapping("/checkSamePeriodExhibition")
    public R<Object> checkSamePeriodExhibition(@RequestBody ExhibitionDTO exhibitionDTO){
        return R.success(baseService.checkSamePeriodExhibition(exhibitionDTO));
    }
}
